import json
import logging
import os
import platform
import shutil
import subprocess
import sys
import threading
import time
from dataclasses import dataclass, asdict
from datetime import datetime
from pathlib import Path
from typing import List, Optional, Dict, Any, Union

import keyboard
import pyperclip
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QSize, QPoint, QPropertyAnimation, QEasingCurve, QMimeData, QUrl, \
    QTimer
from PyQt6.QtGui import QPixmap, QIcon, QAction, QPainter, QDrag
from PyQt6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
                             QListWidget, QFileDialog, QMessageBox, QInputDialog, QListWidgetItem, QLabel, QMenu,
                             QAbstractItemView, QSystemTrayIcon, QMenu as QSystemMenu, QButtonGroup,
                             QDialog, QFrame)

from DarkTheme import DarkTheme
from ImageViewer import posted_img
# 导入主题类
from LightTheme import LightTheme

# 在文件开头的导入部分添加以下导入
import ctypes
from ctypes import wintypes
import platform

# 配置日志系统
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(os.path.join(os.path.expanduser("~"), "clipboard_helper.log"), encoding='utf-8'),
        logging.StreamHandler()
    ]
)


@dataclass
class ClipboardItem:
    content: Union[str, QPixmap, str]  # 内容或图片路径
    content_type: str  # "text" 或 "image"
    group: str
    timestamp: str
    id: str

    def to_dict(self) -> Dict[str, Any]:
        """转换为可序列化的字典"""
        data = asdict(self)
        # 对于图片类型，存储图片路径而非QPixmap对象
        if self.content_type == "image" and isinstance(self.content, QPixmap):
            # 此处应保存图片到文件并返回路径，实际实现见ClipboardHelper
            pass
        return data


class GroupButton(QPushButton):
    """支持拖拽的分组按钮"""

    def __init__(self, group_name: str, parent=None):
        super().__init__(group_name, parent)
        self.group_name = group_name
        self.setAcceptDrops(True)
        self.main_window = None

    def set_main_window(self, main_window):
        """设置主窗口引用"""
        self.main_window = main_window

    def dragEnterEvent(self, event):
        """拖拽进入事件"""
        # 检查是否有自定义的剪贴板项目数据
        if event.mimeData().hasFormat("application/x-clipboard-item"):
            event.acceptProposedAction()
        # 保持原有的文本检查方式以兼容性
        elif event.mimeData().hasText() and event.mimeData().text().startswith("clipboard_item:"):
            event.acceptProposedAction()
        else:
            event.ignore()


    def dropEvent(self, event):
        """放下事件"""
        item_id = None

        # 尝试从自定义 MIME 数据获取项目 ID
        if event.mimeData().hasFormat("application/x-clipboard-item"):
            data = event.mimeData().data("application/x-clipboard-item").data()
            if data.startswith(b"clipboard_item:"):
                item_id = data[len(b"clipboard_item:"):].decode()
        # 保持向后兼容
        elif event.mimeData().hasText() and event.mimeData().text().startswith("clipboard_item:"):
            item_id = event.mimeData().text().split(":", 1)[1]

        if item_id:
            # 获取主窗口实例
            if not self.main_window:
                # 尝试通过parent链找到主窗口
                parent = self.parent()
                while parent and not isinstance(parent, ClipboardHelper):
                    parent = parent.parent()
                self.main_window = parent

            if not self.main_window:
                event.ignore()
                return

            # 查找对应的项目
            item_data = next((item for item in self.main_window.clipboard_items if item.id == item_id), None)

            if item_data:
                # 检查项目是否已经在目标分组中
                if item_data.group == self.group_name:
                    self.main_window.show_themed_message("提示", f"项目已在此分组中: {self.group_name}")
                    event.acceptProposedAction()
                    return

                # 移动项目到新分组z
                old_group = item_data.group
                item_data.group = self.group_name

                # 保存数据
                self.main_window.save_data()

                # 更新界面
                current_group = self.main_window.get_current_group()
                if current_group == old_group or current_group == self.group_name:
                    self.main_window.load_group_items(current_group)
            else:
                self.main_window.show_themed_message("错误", "未找到对应的项目", QMessageBox.Icon.Warning)

            event.acceptProposedAction()
        else:
            event.ignore()


class GlobalHotkeyThread(QThread):
    hotkey_pressed = pyqtSignal()

    def __init__(self, hotkey: str = "alt+z"):
        super().__init__()
        self.running = True
        self.hotkey = hotkey
        self.hotkey_registered = False
        self.re_register_interval = 180000  # 降低到3分钟重新注册一次

    def run(self) -> None:
        """运行热键监听线程"""
        try:
            last_register_time = time.time()

            # 初始注册
            self.re_register_hotkey()
            logging.info(f"已注册全局热键: {self.hotkey}")

            while self.running:
                # 每3分钟重新注册一次热键
                if time.time() - last_register_time > self.re_register_interval / 1000:
                    self.re_register_hotkey()
                    last_register_time = time.time()

                # 添加短暂休眠以减少CPU占用
                time.sleep(0.1)

        except Exception as e:
            logging.error(f"注册热键失败: {e}", exc_info=True)

    def re_register_hotkey(self):
        """重新注册热键"""
        try:
            # 先移除旧的热键（如果存在）
            try:
                if self.hotkey_registered:
                    keyboard.remove_hotkey(self.hotkey)
            except Exception:
                pass  # 忽略移除失败的情况

            # 注册新的热键
            keyboard.add_hotkey(self.hotkey, self.on_hotkey_pressed)
            self.hotkey_registered = True
            logging.info(f"成功重新注册全局热键: {self.hotkey}")

        except Exception as e:
            self.hotkey_registered = False
            logging.error(f"重新注册热键失败: {e}", exc_info=True)
            # 尝试使用不同的注册方式
            try:
                keyboard.unhook_all()
                keyboard.add_hotkey(self.hotkey, self.on_hotkey_pressed)
                self.hotkey_registered = True
                logging.info(f"备用方式注册热键成功: {self.hotkey}")
            except Exception as backup_error:
                logging.error(f"备用方式注册热键也失败: {backup_error}", exc_info=True)


    def on_hotkey_pressed(self) -> None:
        """热键被按下时发出信号"""
        if self.running:
            try:
                self.hotkey_pressed.emit()
            except Exception as e:
                logging.error(f"发送热键信号时出错: {e}", exc_info=True)

    def stop(self) -> None:
        """停止线程"""
        self.running = False
        try:
            if self.hotkey_registered:
                keyboard.remove_hotkey(self.hotkey)
                self.hotkey_registered = False
        except Exception as e:
            logging.error(f"解除热键时出错: {e}", exc_info=True)
        self.quit()
        self.wait(3000)  # 最多等待3秒


class ClipboardMonitorThread(QThread):
    clipboard_changed = pyqtSignal(ClipboardItem)

    def __init__(self):
        super().__init__()
        self.running = True
        self.last_text_content: Optional[str] = None
        self.last_image_hash: Optional[int] = None

    def run(self) -> None:
        """运行剪贴板监控线程"""
        clipboard = QApplication.clipboard()

        while self.running:
            try:
                mime_data = clipboard.mimeData()
                if mime_data.hasText() or mime_data.hasImage():
                    content: Union[str, QPixmap, None] = None
                    content_type: Optional[str] = None
                    content_hash: Optional[int] = None

                    if mime_data.hasImage():
                        image = clipboard.pixmap()
                        if not image.isNull():
                            content = image
                            content_type = "image"
                            # 计算图片哈希值
                            q_image = image.toImage()
                            bits = q_image.constBits()
                            bits.setsize(q_image.sizeInBytes())
                            content_hash = hash(bits.asstring())
                    elif mime_data.hasText():
                        text = clipboard.text()
                        if text and text != self.last_text_content:
                            content = text
                            content_type = "text"
                            content_hash = hash(text)

                    # 确保内容有效且与上次不同
                    if content and content_type:
                        if (content_type == "text" and content != self.last_text_content) or \
                                (content_type == "image" and content_hash != self.last_image_hash):
                            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                            item_id = str(hash(f"{content_type}{timestamp}{content_hash}"))
                            clipboard_item = ClipboardItem(
                                content=content,
                                content_type=content_type,
                                group="临时分组",
                                timestamp=timestamp,
                                id=item_id
                            )

                            # 发送剪贴板内容变更信号
                            self.clipboard_changed.emit(clipboard_item)

                            # 更新最后内容记录
                            if content_type == "text":
                                self.last_text_content = content
                            else:
                                self.last_image_hash = content_hash

                self.msleep(200)  # 缩短检查间隔，提高响应速度
            except Exception as e:
                logging.error(f"剪贴板监控出错: {e}", exc_info=True)
                self.msleep(1000)

    def stop(self) -> None:
        """停止线程"""
        self.running = False
        self.quit()
        self.wait()


class ModernListWidget(QListWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.parent = parent
        self.setHorizontalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
        self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.setFlow(QListWidget.Flow.LeftToRight)
        self.setWrapping(False)
        self.setViewMode(QListWidget.ViewMode.IconMode)
        self.setResizeMode(QListWidget.ResizeMode.Adjust)
        self.setUniformItemSizes(True)
        self.setSpacing(5)
        self.setMouseTracking(True)

        self.setDragEnabled(True)
        self.setAcceptDrops(False)
        self.setDragDropMode(QAbstractItemView.DragDropMode.DragOnly)

        self.update_style_sheet()
        self.update_item_size()

    def update_style_sheet(self):
        if not self.parent:
            return

        # 计算相对边距和间距
        base_margin = int(self.parent.width() * 0.005)
        base_padding = int(self.parent.width() * 0.008)
        border_radius = int(self.parent.width() * 0.006)

        # 根据当前主题应用不同样式
        if hasattr(self.parent, 'is_dark_mode') and self.parent.is_dark_mode:
            self.setStyleSheet(f"""
                QListWidget {{
                    background-color: rgba(30, 30, 30, 0);
                    border: none;
                    border-radius: {border_radius}px;
                    padding: {base_padding}px;
                }}
                QListWidget::item {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(45, 45, 45, 0.95), stop:1 rgba(55, 55, 55, 0.95));
                    border: 1px solid rgba(70, 70, 70, 0.8);
                    border-radius: {border_radius}px;
                    padding: {base_padding}px;
                    margin: {base_margin}px;
                    transition: all 0.2s ease;
                    backdrop-filter: blur(8px);
                }}
                QListWidget::item:selected {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(55, 55, 55, 0.95), stop:1 rgba(65, 65, 65, 0.95));
                    border: 2px solid rgba(100, 100, 100, 0.85);
                    color: #e0e0e0;
                }}
                QListWidget::item:hover {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.95), stop:1 rgba(60, 60, 60, 0.95));
                    border-color: rgba(90, 90, 90, 0.9);
                    transform: translateY(-3px);
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
                }}
                QListWidget::item QTextEdit {{
                    background: transparent;
                    border: none;
                }}
            """)
        else:
            self.setStyleSheet(f"""
                QListWidget {{
                    background-color: rgba(255, 255, 255, 0);
                    border: none;
                    border-radius: {border_radius}px;
                    padding: {base_padding}px;
                }}
                QListWidget::item {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 0.95), stop:1 rgba(245, 245, 245, 0.95));
                    border: 1px solid rgba(220, 220, 220, 0.8);
                    border-radius: {border_radius}px;
                    padding: {base_padding}px;
                    margin: {base_margin}px;
                    transition: all 0.2s ease;
                    backdrop-filter: blur(8px);
                }}
                QListWidget::item:selected {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 0.95), stop:1 rgba(245, 245, 245, 0.95));
                    border: 2px solid rgba(59, 130, 246, 0.8);
                    color: #1a1a1a;
                }}
                QListWidget::item:hover {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(248, 249, 250, 0.95), stop:1 rgba(238, 238, 238, 0.95));
                    border-color: rgba(222, 226, 230, 1);
                    transform: translateY(-3px);
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
                }}
                QListWidget::item QTextEdit {{
                    background: transparent;
                    border: none;
                }}
            """)

    def update_item_size(self):
        if not self.parent:
            return

        # 根据窗口宽度计算项目大小
        item_width = int(self.parent.width() * 0.2)  # 每个项目占窗口宽度的20%
        item_height = int(item_width * 1.2)  # 高度为宽度的1.2倍
        self.setIconSize(QSize(item_width - 20, item_width - 20))  # 图标大小略小于项目宽度

    def wheelEvent(self, event) -> None:
        if event.angleDelta().y() != 0:
            h_scroll = self.horizontalScrollBar()
            h_scroll.setValue(h_scroll.value() - event.angleDelta().y())
        event.accept()

    def startDrag(self, supportedActions):
        item = self.currentItem()
        if item:
            drag = QDrag(self)
            mimeData = QMimeData()

            # 获取项目数据
            item_id = item.data(Qt.ItemDataRole.UserRole)
            if item_id:
                # 查找对应的 ClipboardItem
                clipboard_helper = self.parent
                if clipboard_helper:
                    item_data = next((data for data in clipboard_helper.clipboard_items if data.id == item_id), None)
                    if item_data:
                        # 根据内容类型设置 MIME 数据
                        if item_data.content_type == "text":
                            mimeData.setText(item_data.content)
                            # 添加自定义标识，用于 GroupButton 识别
                            mimeData.setData("application/x-clipboard-item", f"clipboard_item:{item_id}".encode())
                        elif item_data.content_type == "image":
                            # 对于图片，设置文件路径和图像数据
                            file_path = item_data.content  # 修复：原来是 item_data.contentstartDrag
                            if isinstance(file_path, str) and os.path.exists(file_path):
                                # 设置文件路径
                                file_url = QUrl.fromLocalFile(file_path)
                                mimeData.setUrls([file_url])

                                # 如果是图片文件，也设置图像数据
                                if file_path.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif')):
                                    pixmap = QPixmap(file_path)
                                    if not pixmap.isNull():
                                        mimeData.setImageData(pixmap.toImage())

                                # 添加自定义标识，用于 GroupButton 识别
                                mimeData.setData("application/x-clipboard-item", f"clipboard_item:{item_id}".encode())

            drag.setMimeData(mimeData)

            # 设置拖拽 pixmap
            pixmap = QPixmap(self.iconSize())
            pixmap.fill(Qt.GlobalColor.transparent)
            painter = QPainter(pixmap)
            painter.drawPixmap(0, 0, item.icon().pixmap(self.iconSize()))
            painter.end()
            drag.setPixmap(pixmap)
            drag.setHotSpot(QPoint(pixmap.width() // 2, pixmap.height() // 2))

            drag.exec(Qt.DropAction.CopyAction | Qt.DropAction.MoveAction)


class ClipboardHelper(QWidget):
    def __init__(self):
        super().__init__()
        self.config_dir = Path(os.path.expanduser("~")) / ".clipboard_helper"
        self.config_path = self.config_dir / "config.json"
        self.data_path = self.config_dir / "data.json"
        self.images_dir = self.config_dir / "images"

        self.icon_img = QIcon(self.get_resource_path('images/favicon.ico'))

        self.hide_on_click_outside = True

        self.config_dir.mkdir(exist_ok=True)
        self.images_dir.mkdir(exist_ok=True)

        self.config = self.load_config()
        self.clipboard_items: List[ClipboardItem] = self.load_data()
        self.groups = self.config.get("groups", ["临时分组"])
        self.max_groups = 15
        self.max_items_per_group = self.config.get("max_items_per_group", 100)
        self.hotkey = self.config.get("hotkey", "alt+z")

        # 主题相关设置
        self.is_dark_mode = self.config.get("dark_mode", False)
        self.light_theme = LightTheme()
        self.dark_theme = DarkTheme()

        self.init_ui()
        self.setup_tray_icon()
        self.setup_global_hotkey()
        self.setup_clipboard_monitor()

        self.group_buttons = []
        self.group_button_group = QButtonGroup(self)
        self.group_button_group.setExclusive(True)
        self.update_group_buttons()

        logging.info("剪贴板助手已启动")

        self.pasting_in_progress = False

        self.hotkey_check_timer = QTimer(self)
        self.hotkey_check_timer.timeout.connect(self.check_and_renew_hotkey)
        self.hotkey_check_timer.start(15000)  # 降低到15秒检查一次

        QApplication.instance().applicationStateChanged.connect(self.on_app_state_changed)

        # 添加权限检查相关属性
        self.permission_check_timer = QTimer(self)
        self.permission_check_timer.timeout.connect(self.check_and_fix_permissions)
        self.permission_check_timer.start(30000)  # 每30秒检查一次

        # 初始化时检查一次权限
        QTimer.singleShot(1000, self.check_and_fix_permissions)


    def check_windows_admin_privileges(self):
        """检查Windows系统下是否具有管理员权限"""
        try:
            if platform.system().lower() != 'windows':
                return True

            # 检查是否具有管理员权限
            return ctypes.windll.shell32.IsUserAnAdmin()
        except:
            return False

    def fix_foreground_window_permission(self):
        """修复前台窗口权限问题（Windows）"""
        try:
            if platform.system().lower() != 'windows':
                return True

            # 使用ctypes调用Windows API
            user32 = ctypes.windll.user32
            kernel32 = ctypes.windll.kernel32

            # 获取当前进程ID
            pid = wintypes.DWORD()
            current_window = user32.GetForegroundWindow()
            user32.GetWindowThreadProcessId(current_window, ctypes.byref(pid))

            # 获取当前进程ID
            current_pid = kernel32.GetCurrentProcessId()

            # 如果前台窗口不是当前应用，则尝试获取权限
            if pid.value != current_pid:
                # 尝试设置前台窗口权限
                user32.AllowSetForegroundWindow(-1)  # ASFW_ANY

            return True
        except Exception as e:
            logging.error(f"修复前台窗口权限时出错: {e}")
            return False

    def check_and_fix_permissions(self):
        """检查并修复可能影响全局快捷键的权限问题"""
        try:
            # 重新注册热键
            if hasattr(self, 'hotkey_thread') and self.hotkey_thread.isRunning():
                self.hotkey_thread.re_register_hotkey()

            # 在Windows系统上检查特殊权限
            if platform.system().lower() == 'windows':
                self.fix_foreground_window_permission()

            logging.debug("权限检查完成")

        except Exception as e:
            logging.error(f"权限检查和修复时出错: {e}")

    def on_app_state_changed(self, state):
        """应用状态变化时重新注册热键"""
        try:
            # 当应用状态变化时重新注册热键
            if hasattr(self, 'hotkey_thread') and self.hotkey_thread.isRunning():
                QTimer.singleShot(1000, self.hotkey_thread.re_register_hotkey)

            # 状态变化时也检查权限z
            QTimer.singleShot(2000, self.check_and_fix_permissions)

        except Exception as e:
            logging.error(f"应用状态变化时重新注册热键失败: {e}", exc_info=True)

    def init_ui(self) -> None:
        self.setWindowTitle('剪贴板助手')
        self.setWindowIcon(self.icon_img)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
        self.setWindowFlags(
            Qt.WindowType.FramelessWindowHint |
            Qt.WindowType.WindowStaysOnTopHint |
            Qt.WindowType.NoDropShadowWindowHint
        )

        # 自适应窗口高度
        screen = QApplication.primaryScreen()
        screen_rect = screen.geometry()
        window_height = int(screen_rect.height() * 0.28)  # 窗口高度为屏幕高度的28%

        self.setGeometry(0, screen_rect.height() - window_height,
                         screen_rect.width(), window_height)

        # 创建主容器
        self.main_container = QFrame(self)
        self.main_container.setObjectName("MainContainer")
        self.main_container.setGeometry(self.rect())

        # 动态计算字体大小
        base_font_size = int(screen_rect.width() * 0.008)  # 基于屏幕宽度的0.8%计算字体大小
        min_font_size = 10
        max_font_size = 16
        font_size = max(min(base_font_size, max_font_size), min_font_size)  # 限制字体大小范围

        # 统一圆角
        border_radius = 6

        # 应用初始主题
        self.apply_theme()

        # 创建主布局
        main_layout = QVBoxLayout(self.main_container)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)

        # 顶部分组栏
        self.group_bar_layout = QHBoxLayout()
        self.group_bar_layout.setSpacing(5)
        self.group_bar_layout.setContentsMargins(16, 8, 16, 0)  # 底部不留边距，由list_container控制

        # 右侧功能按钮区
        self.tools_layout = QHBoxLayout()
        self.tools_layout.setSpacing(8)

        # 隐藏界面
        hide_btn = QPushButton("➖")
        hide_btn.setProperty("iconOnly", "true")
        hide_btn.setToolTip("隐藏界面")
        hide_btn.setObjectName("hide-icon")
        hide_btn.setCursor(Qt.CursorShape.PointingHandCursor)

        # 删除按钮
        clear_btn = QPushButton("🗑️")
        clear_btn.setProperty("iconOnly", "true")
        clear_btn.setToolTip("清空当前分组")
        clear_btn.setObjectName("delete-icon")
        clear_btn.setCursor(Qt.CursorShape.PointingHandCursor)

        # 设置按钮
        settings_btn = QPushButton("⚙️")
        settings_btn.setProperty("iconOnly", "true")
        settings_btn.setToolTip("设置")
        settings_btn.setObjectName("settings-icon")
        settings_btn.setCursor(Qt.CursorShape.PointingHandCursor)

        # 添加分组按钮
        add_group_btn = QPushButton("➕")
        add_group_btn.setProperty("iconOnly", "true")
        add_group_btn.setToolTip("添加分组")
        add_group_btn.setObjectName("add-icon")
        add_group_btn.setCursor(Qt.CursorShape.PointingHandCursor)

        # 退出按钮
        exit_btn = QPushButton("❌")
        exit_btn.setProperty("iconOnly", "true")
        exit_btn.setToolTip("退出程序")
        exit_btn.setObjectName("exit-icon")
        exit_btn.setCursor(Qt.CursorShape.PointingHandCursor)

        # 主题切换按钮
        self.theme_btn = QPushButton("🌙" if self.is_dark_mode else "☀️")
        self.theme_btn.setProperty("iconOnly", "true")
        self.theme_btn.setToolTip("切换深色/浅色模式")
        self.theme_btn.clicked.connect(self.toggle_theme)
        self.theme_btn.setCursor(Qt.CursorShape.PointingHandCursor)

        self.tools_layout.addWidget(hide_btn)
        self.tools_layout.addWidget(add_group_btn)
        self.tools_layout.addWidget(clear_btn)
        self.tools_layout.addWidget(settings_btn)
        self.tools_layout.addWidget(self.theme_btn)
        self.tools_layout.addWidget(exit_btn)  # 添加退出按钮


        self.group_bar_layout.addStretch()
        self.group_bar_layout.addLayout(self.tools_layout)

        self.item_list = ModernListWidget(self)
        self.item_list.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
        self.item_list.customContextMenuRequested.connect(self.show_context_menu)
        self.item_list.itemDoubleClicked.connect(self.on_item_double_clicked)
        self.item_list.setMinimumWidth(200)
        self.item_list.setMinimumHeight(int(window_height * 0.9))

        list_container = QWidget()
        list_layout = QVBoxLayout(list_container)
        list_layout.setContentsMargins(0, 0, 0, 10)
        list_layout.addWidget(self.item_list)

        main_layout.addLayout(self.group_bar_layout)
        main_layout.addWidget(list_container)

        hide_btn.clicked.connect(self.hide_window)
        clear_btn.clicked.connect(self.clear_current_group)
        settings_btn.clicked.connect(self.open_settings)
        add_group_btn.clicked.connect(self.add_group)
        exit_btn.clicked.connect(self.exit_application)  # 连接退出按钮的信号

        self.load_group_items("临时分组")

    def check_and_renew_hotkey(self):
        """检查并重新注册热键"""
        try:
            # 检查热键线程是否仍在运行
            if not hasattr(self, 'hotkey_thread') or not self.hotkey_thread.isRunning():
                logging.warning("热键线程未运行，重新启动")
                self.setup_global_hotkey()
            else:
                # 触发一次重新注册
                if hasattr(self.hotkey_thread, 're_register_hotkey'):
                    self.hotkey_thread.re_register_hotkey()

            # 额外验证热键是否工作
            if hasattr(self, 'hotkey_thread'):
                # 如果热键未注册，则重新注册
                if not getattr(self.hotkey_thread, 'hotkey_registered', False):
                    self.hotkey_thread.re_register_hotkey()

        except Exception as e:
            logging.error(f"检查和重新注册热键时出错: {e}", exc_info=True)
            # 出错时重新初始化整个热键系统
            try:
                self.setup_global_hotkey()
            except Exception as init_error:
                logging.error(f"重新初始化热键系统失败: {init_error}", exc_info=True)

    def apply_theme(self):
        """应用当前主题，包括全局样式设置"""
        screen = QApplication.primaryScreen()
        screen_rect = screen.geometry()
        base_font_size = int(screen_rect.width() * 0.008)
        min_font_size = 10
        max_font_size = 16
        font_size = max(min(base_font_size, max_font_size), min_font_size)
        border_radius = 6

        # 设置主窗口样式
        if self.is_dark_mode:
            self.setStyleSheet(f"""
                #MainContainer {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(30, 30, 30, 0.95), stop:1 rgba(40, 40, 40, 0.95));
                    border-radius: {border_radius}px;
                    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
                    backdrop-filter: blur(12px);
                    margin: 0px;
                    padding: 0px;
                }}
                QWidget {{
                    color: #e0e0e0;
                    font-family: 'Segoe UI', 'Inter', 'Roboto', sans-serif;
                    font-size: {font_size}px;
                }}
                QPushButton {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: {int(border_radius * 0.8)}px;
                    padding: 8px 16px;
                    min-height: {int(screen_rect.height() * 0.03)}px;
                    transition: all 0.2s ease;
                    font-weight: 500;
                }}
                QPushButton:hover {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                    border-color: rgba(90, 90, 90, 0.9);
                }}
                QPushButton:pressed {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(70, 70, 70, 0.9), stop:1 rgba(80, 80, 80, 0.9));
                }}
                QPushButton:checked {{
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(80, 80, 80, 0.9), stop:1 rgba(90, 90, 90, 0.9));
                    color: white;
                    border-color: rgba(100, 100, 100, 0.8);
                }}
                QLabel {{
                    color: #b0b0b0;
                }}
                QPushButton[iconOnly="true"] {{
                    min-width: {int(screen_rect.height() * 0.04)}px;
                    max-width: {int(screen_rect.height() * 0.04)}px;
                    min-height: {int(screen_rect.height() * 0.04)}px;
                    max-height: {int(screen_rect.height() * 0.04)}px;
                    border-radius: {int(screen_rect.height() * 0.015)}px;
                    padding: 0;
                    background-color: rgba(55, 55, 55, 0.9);
                    border: 1px solid rgba(75, 75, 75, 0.8);
                }}
            """)
        else:
            self.setStyleSheet(f"""
                #MainContainer {{
                    background-color: rgba(255, 255, 255, 0.85);
                    border-radius: {border_radius}px;
                    box-shadow: 0 8px 32px rgba(0, 0, 0, .08);
                    backdrop-filter: blur(12px);
                }}
                QWidget {{
                    color: #1a1a1a;
                    font-family: 'Segoe UI', 'Inter', 'Roboto', 'Helvetica Neue', sans-serif;
                    font-size: {font_size}px;
                }}
                QPushButton {{
                    background-color: rgba(255, 255, 255, 0.7);
                    border: 1px solid rgba(222, 226, 230, 0.7);
                    border-radius: {int(border_radius * 0.8)}px;
                    padding: {int(screen_rect.height() * 0.01)}px {int(screen_rect.width() * 0.008)}px;
                    min-height: {int(screen_rect.height() * 0.03)}px;
                    transition: all 0.2s ease;
                    font-weight: 500;
                }}
                QPushButton:hover {{
                    background-color: rgba(248, 249, 250, 0.9);
                    border-color: rgba(222, 226, 230, 0.9);
                }}
                QPushButton:pressed {{
                    background-color: rgba(233, 236, 239, 0.9);
                }}
                QPushButton:checked {{
                    background-color: rgba(59, 130, 246, 0.8);
                    color: white;
                    border-color: rgba(59, 130, 246, 0.8);
                }}
                QLabel {{
                    color: #495057;
                }}
                QPushButton[iconOnly="true"] {{
                    min-width: {int(screen_rect.height() * 0.04)}px;
                    max-width: {int(screen_rect.height() * 0.04)}px;
                    min-height: {int(screen_rect.height() * 0.04)}px;
                    max-height: {int(screen_rect.height() * 0.04)}px;
                    border-radius: {int(screen_rect.height() * 0.015)}px;
                    padding: 0;
                    background-color: rgba(245, 245, 245, 0.9);
                    border: 1px solid rgba(220, 220, 220, 0.8);
                }}
            """)

        # 设置全局样式，影响所有标准对话框
        app = QApplication.instance()
        if self.is_dark_mode:
            app.setStyleSheet("""
                QMessageBox, QInputDialog, QDialog {
                    background-color: rgba(30, 30, 30, 0.95);
                    color: #e0e0e0;
                    border-radius: 12px;
                }
                QMessageBox QLabel, QInputDialog QLabel, QDialog QLabel {
                    color: #e0e0e0;
                }
                QMessageBox QPushButton, QInputDialog QPushButton, QDialog QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #e0e0e0;
                }
                QMessageBox QPushButton:hover, QInputDialog QPushButton:hover, QDialog QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                }
                QInputDialog QLineEdit, QInputDialog QSpinBox {
                    background-color: rgba(45, 45, 45, 0.9);
                    color: #e0e0e0;
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px;
                }
                QPushButton[iconOnly="true"] {
                    min-width: {int(screen_rect.height() * 0.04)}px;
                    max-width: {int(screen_rect.height() * 0.04)}px;
                    min-height: {int(screen_rect.height() * 0.04)}px;
                    max-height: {int(screen_rect.height() * 0.04)}px;
                    border-radius: {int(screen_rect.height() * 0.015)}px;
                    padding: 0;
                    background-color: rgba(55, 55, 55, 0.9);
                    border: 1px solid rgba(75, 75, 75, 0.8);
                }
                QPushButton[iconOnly="true"]:hover {
                    background-color: rgba(70, 70, 70, 0.9);
                    border: 1px solid rgba(90, 90, 90, 0.9);
                }
            """)
        else:
            app.setStyleSheet("""
                QMessageBox, QInputDialog, QDialog {
                    background-color: rgba(255, 255, 255, 0.95);
                    color: #1a1a1a;
                    border-radius: 12px;
                }
                QMessageBox QLabel, QInputDialog QLabel, QDialog QLabel {
                    color: #495057;
                }
                QMessageBox QPushButton, QInputDialog QPushButton, QDialog QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(250, 250, 250, 0.9), stop:1 rgba(240, 240, 240, 0.9));
                    border: 1px solid rgba(220, 220, 220, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #333333;
                }
                QMessageBox QPushButton:hover, QInputDialog QPushButton:hover, QDialog QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(245, 245, 245, 0.9), stop:1 rgba(235, 235, 235, 0.9));
                }
                QInputDialog QLineEdit, QInputDialog QSpinBox {
                    background-color: rgba(255, 255, 255, 0.9);
                    color: #1a1a1a;
                    border: 1px solid rgba(222, 226, 230, 0.8);
                    border-radius: 8px;
                    padding: 6px;
                }
                QPushButton[iconOnly="true"] {
                    min-width: {int(screen_rect.height() * 0.04)}px;
                    max-width: {int(screen_rect.height() * 0.04)}px;
                    min-height: {int(screen_rect.height() * 0.04)}px;
                    max-height: {int(screen_rect.height() * 0.04)}px;
                    border-radius: {int(screen_rect.height() * 0.015)}px;
                    padding: 0;
                    background-color: rgba(245, 245, 245, 0.9);
                    border: 1px solid rgba(220, 220, 220, 0.8);
                }
                QPushButton[iconOnly="true"]:hover {
                    background-color: rgba(230, 230, 230, 0.9);
                    border: 1px solid rgba(200, 200, 200, 0.9);
                }
            """)

        # 更新列表样式
        if hasattr(self, 'item_list'):
            self.item_list.update_style_sheet()

    def exit_application(self):
        """
        退出应用程序
        """
        # 创建确认对话框
        msg_box = QMessageBox(self)
        msg_box.setWindowTitle("确认退出")
        msg_box.setText("确定要退出剪贴板助手吗？")
        msg_box.setIcon(QMessageBox.Icon.Question)
        msg_box.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        msg_box.setDefaultButton(QMessageBox.StandardButton.No)

        # 应用主题样式
        if self.is_dark_mode:
            msg_box.setStyleSheet("""
                QMessageBox {
                    background-color: rgba(30, 30, 30, 0.95);
                    color: #e0e0e0;
                    border-radius: 12px;
                }
                QMessageBox QLabel {
                    color: #e0e0e0;
                }
                QMessageBox QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #e0e0e0;
                }
                QMessageBox QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                }
            """)
        else:
            msg_box.setStyleSheet("""
                QMessageBox {
                    background-color: rgba(255, 255, 255, 0.95);
                    color: #1a1a1a;
                    border-radius: 12px;
                }
                QMessageBox QLabel {
                    color: #495057;
                }
                QMessageBox QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(250, 250, 250, 0.9), stop:1 rgba(240, 240, 240, 0.9));
                    border: 1px solid rgba(220, 220, 220, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #333333;
                }
                QMessageBox QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(245, 245, 245, 0.9), stop:1 rgba(235, 235, 235, 0.9));
                }
            """)

        # 执行对话框并获取结果
        result = msg_box.exec()

        # 如果用户确认退出，则关闭应用程序
        if result == QMessageBox.StandardButton.Yes:
            QApplication.quit()

    def show_themed_message(self, title, text, icon=QMessageBox.Icon.Information):
        """显示带主题样式的消息框"""
        try:
            msg_box = QMessageBox(self)  # 确保设置父窗口为当前主窗口
            msg_box.setWindowTitle(title)
            msg_box.setText(text)
            msg_box.setIcon(icon)
            msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)

            # 应用主题样式
            if self.is_dark_mode:
                msg_box.setStyleSheet("""
                    QMessageBox {
                        background-color: rgba(30, 30, 30, 0.95);
                        color: #e0e0e0;
                        border-radius: 12px;
                    }
                    QMessageBox QLabel {
                        color: #e0e0e0;
                    }
                    QMessageBox QPushButton {
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                        border: 1px solid rgba(75, 75, 75, 0.8);
                        border-radius: 8px;
                        padding: 6px 14px;
                        color: #e0e0e0;
                    }
                    QMessageBox QPushButton:hover {
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                    }
                """)
            else:
                msg_box.setStyleSheet("""
                    QMessageBox {
                        background-color: rgba(255, 255, 255, 0.95);
                        color: #1a1a1a;
                        border-radius: 12px;
                    }
                    QMessageBox QLabel {
                        color: #495057;
                    }
                    QMessageBox QPushButton {
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(250, 250, 250, 0.9), stop:1 rgba(240, 240, 240, 0.9));
                        border: 1px solid rgba(220, 220, 220, 0.8);
                        border-radius: 8px;
                        padding: 6px 14px;
                        color: #333333;
                    }
                    QMessageBox QPushButton:hover {
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(245, 245, 245, 0.9), stop:1 rgba(235, 235, 235, 0.9));
                    }
                """)

            # 显示对话框并等待用户响应
            result = msg_box.exec()
            return result
        except Exception as e:
            logging.error(f"显示消息框时出错: {e}", exc_info=True)
            # 异常情况下使用基本消息框确保用户能看到错误
            QMessageBox.critical(self, "错误", f"显示消息时出错: {str(e)}")

    def toggle_theme(self):
        """切换深色/浅色主题"""
        self.is_dark_mode = not self.is_dark_mode
        self.theme_btn.setText("☀️" if self.is_dark_mode else "🌙")
        self.config["dark_mode"] = self.is_dark_mode
        self.save_config()
        self.apply_theme()
        self.item_list.update_style_sheet()
        self.update_group_buttons()

    def resizeEvent(self, event):
        """窗口大小改变时更新UI元素"""
        # 更新列表项大小和样式
        if hasattr(self, 'item_list'):
            self.item_list.update_item_size()
            self.item_list.update_style_sheet()

        # 更新窗口位置（保持在屏幕底部）
        screen = QApplication.primaryScreen()
        screen_rect = screen.geometry()
        self.setGeometry(0, screen_rect.height() - self.height(), screen_rect.width(), self.height())

        super().resizeEvent(event)

    def show_author_info(self) -> None:
        self.show_themed_message("作者信息", "作者QQ：1505448035")

    def get_resource_path(self, relative_path):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(sys._MEIPASS, relative_path)
        return os.path.join(os.path.abspath("."), relative_path)

    def setup_tray_icon(self) -> None:
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(self.icon_img)
        self.tray_icon.setToolTip("剪贴板助手")

        tray_menu = QSystemMenu()

        show_action = QAction("显示", self)
        show_action.triggered.connect(self.show)
        tray_menu.addAction(show_action)

        hide_action = QAction("隐藏", self)
        hide_action.triggered.connect(self.hide)
        tray_menu.addAction(hide_action)

        exit_action = QAction("退出", self)
        exit_action.triggered.connect(QApplication.quit)
        tray_menu.addAction(exit_action)

        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()

        self.tray_icon.activated.connect(self.on_tray_icon_activated)

    def on_tray_icon_activated(self, reason: QSystemTrayIcon.ActivationReason) -> None:
        if reason == QSystemTrayIcon.ActivationReason.Trigger:
            self.toggle_visibility()

    def setup_global_hotkey(self) -> None:
        if hasattr(self, 'hotkey_thread') and self.hotkey_thread.isRunning():
            self.hotkey_thread.stop()

        self.hotkey_thread = GlobalHotkeyThread(self.hotkey)
        self.hotkey_thread.hotkey_pressed.connect(self.toggle_visibility)
        self.hotkey_thread.start()

        self.hotkey_thread.finished.connect(self.on_hotkey_thread_finished)

    def on_hotkey_thread_finished(self):
        logging.info("热键监听线程已结束")

    def setup_clipboard_monitor(self) -> None:
        self.clipboard_thread = ClipboardMonitorThread()
        self.clipboard_thread.clipboard_changed.connect(self.on_clipboard_changed)
        self.clipboard_thread.start()

    def toggle_visibility(self) -> None:
        if self.pasting_in_progress and self.isVisible():
            logging.info("粘贴操作正在进行中，跳过隐藏窗口")
            return
        if self.isVisible() and not self.isMinimized():
            self.hide_animation = QPropertyAnimation(self, b"windowOpacity")
            self.hide_animation.setDuration(200)
            self.hide_animation.setStartValue(1.0)
            self.hide_animation.setEndValue(0.0)
            self.hide_animation.setEasingCurve(QEasingCurve.Type.InOutQuad)
            self.hide_animation.finished.connect(self.hide)
            self.hide_animation.start()
        else:
            self.setWindowOpacity(0.0)
            self.show()
            self.raise_()
            self.activateWindow()
            self.show_animation = QPropertyAnimation(self, b"windowOpacity")
            self.show_animation.setDuration(200)
            self.show_animation.setStartValue(0.0)
            self.show_animation.setEndValue(1.0)
            self.show_animation.setEasingCurve(QEasingCurve.Type.InOutQuad)
            self.show_animation.start()

    def on_clipboard_changed(self, item: ClipboardItem) -> None:
        current_group = "临时分组"
        item.group = current_group

        group_items = [i for i in self.clipboard_items if i.group == current_group]
        if len(group_items) >= self.max_items_per_group:
            oldest_item = min(group_items, key=lambda x: x.timestamp)
            self.remove_item(oldest_item)

        if item.content_type == "image" and isinstance(item.content, QPixmap):
            image_path = self.images_dir / f"{item.id}.png"
            item.content.save(str(image_path))
            item.content = str(image_path)

        self.clipboard_items.append(item)

        all_group_items = [i for i in self.clipboard_items if i.group == "临时分组"]
        reservations_num = 15
        if len(all_group_items) > reservations_num:
            all_group_items.sort(key=lambda x: x.timestamp, reverse=True)
            old_items = all_group_items[reservations_num:]
            for item in old_items:
                self.remove_item(item)

        self.save_data()

        if current_group == self.get_current_group():
            self.load_group_items(current_group)

    def load_group_items(self, group_name: str) -> None:
        self.item_list.clear()
        group_items = [item for item in self.clipboard_items if item.group == group_name]

        group_items.sort(key=lambda x: x.timestamp, reverse=True)

        for item in group_items:
            list_item = QListWidgetItem()

            # 根据窗口宽度计算项目大小
            item_width = int(self.width() * 0.1)  # 项目宽度为窗口宽度的10%
            item_height = int(item_width * 1.1)  # 高度为宽度的1.1倍
            list_item.setSizeHint(QSize(item_width, item_height))

            if item.content_type == "text":
                preview = item.content[:350] + "..." if len(item.content) > 350 else item.content
                list_item.setText(preview)
                list_item.setTextAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)
            else:
                list_item.setText(f"{item.timestamp}")
                try:
                    pixmap = QPixmap(item.content)
                    if not pixmap.isNull():
                        scaled_pixmap = pixmap.scaled(
                            int(item_width * 0.9), int(item_width * 0.9),
                            Qt.AspectRatioMode.KeepAspectRatio,
                            Qt.TransformationMode.SmoothTransformation
                        )
                        list_item.setIcon(QIcon(scaled_pixmap))
                except Exception as e:
                    logging.error(f"加载图片缩略图失败: {e}")

            list_item.setData(Qt.ItemDataRole.UserRole, item.id)
            self.item_list.addItem(list_item)

    def show_context_menu(self, position: QPoint) -> None:
        item = self.item_list.itemAt(position)
        if not item:
            return

        menu = QMenu()

        copy_action = menu.addAction("复制到剪贴板")
        copy_action.triggered.connect(lambda: self.copy_to_clipboard(item))

        item_id = item.data(Qt.ItemDataRole.UserRole)
        item_data = next((data for data in self.clipboard_items if data.id == item_id), None)

        if item_data and item_data.content_type == "image":
            pin_action = menu.addAction("钉图")
            pin_action.triggered.connect(lambda: self.pin_item(item))

        delete_action = menu.addAction("删除")
        delete_action.triggered.connect(lambda: self.delete_item(item))

        menu.exec(self.item_list.mapToGlobal(position))

    def pin_item(self, item: QListWidgetItem) -> None:
        try:
            logging.info("用户点击了钉图功能")

            item_id = item.data(Qt.ItemDataRole.UserRole)
            item_data = next((data for data in self.clipboard_items if data.id == item_id), None)

            if item_data and item_data.content_type == "image":
                threading.Thread(target=posted_img, args=(item_data.content,)).start()
                self.hide()

        except Exception as e:
            logging.error(f"钉图项目时发生异常: {e}", exc_info=True)
            self.show_themed_message(
                "钉图功能失败",
                f"点击钉图后发生错误:\n{str(e)}\n\n详细信息已记录到日志文件",
                QMessageBox.Icon.Critical
            )

    def copy_to_clipboard(self, item: QListWidgetItem) -> None:
        try:
            item_id = item.data(Qt.ItemDataRole.UserRole)
            item_data = next((data for data in self.clipboard_items if data.id == item_id), None)

            if item_data:
                clipboard = QApplication.clipboard()
                if item_data.content_type == "text":
                    clipboard.setText(item_data.content)
                    QApplication.clipboard().setText(item_data.content)
                    QTimer.singleShot(100, self.send_paste_shortcut)
                else:
                    pixmap = QPixmap(item.content)
                    if not pixmap.isNull():
                        clipboard.setPixmap(pixmap)
                        self.show_themed_message("提示", "图片已复制到剪贴板")
                    else:
                        self.show_themed_message("警告", "无法加载图片数据", QMessageBox.Icon.Warning)
            else:
                self.show_themed_message("警告", "未找到对应的项目数据", QMessageBox.Icon.Warning)

        except Exception as e:
            logging.error(f"复制到剪贴板时出错: {e}", exc_info=True)
            self.show_themed_message("错误", f"复制到剪贴板时出错: {str(e)}", QMessageBox.Icon.Critical)

    def send_paste_shortcut(self):
        try:
            keyboard.press_and_release('ctrl+v')
            logging.info("已发送粘贴快捷键(Ctrl+V)")
        except Exception as e:
            logging.error(f"模拟粘贴操作失败: {e}", exc_info=True)
            self.show_themed_message("提示", "内容已复制到剪贴板，请使用 Ctrl+V 粘贴")

    def on_item_double_clicked(self, item: QListWidgetItem) -> None:
        try:
            item_id = item.data(Qt.ItemDataRole.UserRole)
            item_data = next((data for data in self.clipboard_items if data.id == item_id), None)

            if item_data:
                self.pasting_in_progress = True

                if item_data.content_type == "text":
                    self.hide()

                    pyperclip.copy(item_data.content)
                    time.sleep(0.1)

                    keyboard.press_and_release('ctrl+v')
                else:
                    self.paste_image_file(item_data.content)

            else:
                self.show_themed_message("警告", "未找到对应的项目数据", QMessageBox.Icon.Warning)

            self.pasting_in_progress = False
        except Exception as e:
            logging.error(f"双击粘贴时出错: {e}", exc_info=True)
            self.show_themed_message("错误", f"双击粘贴时出错: {str(e)}", QMessageBox.Icon.Critical)
            self.pasting_in_progress = False

    def paste_image_file(self, image_path: str) -> None:
        try:
            self.hide()
            self.copy_file_to_clipboard_powershell(image_path)

            keyboard.press_and_release('ctrl+v')

        except Exception as e:
            logging.error(f"粘钉图片文件时出错: {e}", exc_info=True)
            self.show_themed_message("提示", "图片已准备好，请使用 Ctrl+V 粘贴")

    def copy_file_to_clipboard(self, file_path: str) -> None:
        try:
            mime_data = QMimeData()
            file_url = QUrl.fromLocalFile(file_path)
            mime_data.setUrls([file_url])

            if file_path.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif')):
                pixmap = QPixmap(file_path)
                if not pixmap.isNull():
                    mime_data.setImageData(pixmap.toImage())

            clipboard = QApplication.clipboard()
            clipboard.setMimeData(mime_data)

        except Exception as e:
            logging.error(f"复制文件到剪贴板时出错: {e}", exc_info=True)
            raise

    def copy_file_to_clipboard_powershell(self, file_path):
        try:
            system = platform.system()

            if system == "Windows":
                powershell_command = f'powershell -command "Set-Clipboard -Path \'{file_path}\'"'
                subprocess.run(powershell_command, shell=True, check=True)
                return f"文件已成功复制到剪贴板，可以在需要的位置粘贴"

        except subprocess.CalledProcessError as e:
            raise Exception(f"复制文件到剪贴板时出错: {str(e)}")
        except Exception as e:
            raise Exception(f"操作失败: {str(e)}")

    def get_current_group(self) -> str:
        checked_button = self.group_button_group.checkedButton()
        return checked_button.text() if checked_button else "临时分组"

    def update_group_buttons(self) -> None:
        for btn in self.group_buttons:
            self.group_bar_layout.removeWidget(btn)
            self.group_button_group.removeButton(btn)
            btn.deleteLater()
        self.group_buttons.clear()

        for group_name in self.groups:
            btn = GroupButton(group_name, self)
            btn.set_main_window(self)
            btn.setCheckable(True)
            btn.setMinimumWidth(90)

            # 根据当前主题设置按钮样式
            if self.is_dark_mode:
                btn.setStyleSheet("""
                    QPushButton {
                        border-radius: 8px;
                        padding: 6px 14px;
                        font-weight: 500;
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                        border: 1px solid rgba(75, 75, 75, 0.8);
                        color: #e0e0e0;
                    }
                    QPushButton:hover {
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                        border-color: rgba(90, 90, 90, 0.9);
                    }
                    QPushButton:checked {
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(80, 80, 80, 0.9), stop:1 rgba(90, 90, 90, 0.9));
                        color: white;
                        border-color: rgba(100, 100, 100, 0.8);
                    }
                """)
            else:
                btn.setStyleSheet("""
                    QPushButton {
                        border-radius: 8px;
                        padding: 6px 14px;
                        font-weight: 500;
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(250, 250, 250, 0.9), stop:1 rgba(240, 240, 240, 0.9));
                        border: 1px solid rgba(220, 220, 220, 0.8);
                        color: #333333;
                    }z
                    QPushButton:hover {
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(245, 245, 245, 0.9), stop:1 rgba(235, 235, 235, 0.9));
                        border-color: rgba(200, 200, 200, 0.9);
                    }
                    QPushButton:checked {
                        background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(220, 220, 220, 0.9), stop:1 rgba(200, 200, 200, 0.9));
                        color: #333333;
                        border-color: rgba(180, 180, 180, 0.8);
                    }
                """)

            self.group_bar_layout.insertWidget(len(self.group_buttons), btn)
            self.group_button_group.addButton(btn)
            self.group_buttons.append(btn)
            btn.clicked.connect(lambda checked, g=group_name: self.on_group_button_clicked(g))
            btn.setCursor(Qt.CursorShape.PointingHandCursor)

            btn.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
            btn.customContextMenuRequested.connect(lambda pos, g=group_name: self.show_group_context_menu(pos, g))

        if self.group_buttons:
            self.group_buttons[0].setChecked(True)
            self.load_group_items(self.groups[0])

    def show_group_context_menu(self, pos, group_name):
        menu = QMenu()
        modify_action = QAction("修改分组", self)
        delete_action = QAction("删除分组", self)

        modify_action.triggered.connect(lambda: self.modify_group(group_name))
        delete_action.triggered.connect(lambda: self.delete_group(group_name))

        menu.addAction(modify_action)
        menu.addAction(delete_action)

        btn = self.sender()
        menu.exec(btn.mapToGlobal(pos))

    def modify_group(self, old_name):
        new_name, ok = QInputDialog.getText(self, "修改分组", "请输入新的分组名称:", text=old_name)
        if ok and new_name:
            if new_name in self.groups:
                self.show_themed_message("警告", "分组名称已存在", QMessageBox.Icon.Warning)
                return
            index = self.groups.index(old_name)
            self.groups[index] = new_name
            for item in self.clipboard_items:
                if item.group == old_name:
                    item.group = new_name
            self.config["groups"] = self.groups
            self.save_config()
            self.update_group_buttons()
            logging.info(f"修改分组: {old_name} -> {new_name}")

    def on_group_button_clicked(self, group_name: str) -> None:
        self.load_group_items(group_name)

    def add_group(self) -> None:
        if len(self.groups) >= self.max_groups:
            self.show_themed_message("警告", f"最多只能创建{self.max_groups}个分组", QMessageBox.Icon.Warning)
            return

        group_name, ok = QInputDialog.getText(self, "添加分组", "请输入分组名称:")
        if ok and group_name:
            if group_name in self.groups:
                self.show_themed_message("警告", "分组名称已存在", QMessageBox.Icon.Warning)
                return

            self.groups.append(group_name)
            self.config["groups"] = self.groups
            self.save_config()
            self.update_group_buttons()
            logging.info(f"添加新分组: {group_name}")

    def delete_group(self, group_name) -> None:
        if group_name == "临时分组":
            self.show_themed_message("警告", "默认分组不能删除", QMessageBox.Icon.Warning)
            return

        # 创建确认对话框，明确设置父窗口为self
        msg_box = QMessageBox(self)
        msg_box.setWindowTitle("确认")
        msg_box.setText(f"确定要删除分组 '{group_name}' 吗？")
        msg_box.setIcon(QMessageBox.Icon.Question)
        msg_box.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        msg_box.setDefaultButton(QMessageBox.StandardButton.No)  # 默认选择"否"

        # 应用主题样式
        if self.is_dark_mode:
            msg_box.setStyleSheet("""
                QMessageBox {
                    background-color: rgba(30, 30, 30, 0.95);
                    color: #e0e0e0;
                    border-radius: 12px;
                }
                QMessageBox QLabel {
                    color: #e0e0e0;
                }
                QMessageBox QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #e0e0e0;
                }
                QMessageBox QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                }
            """)

        # 执行对话框并获取结果
        result = msg_box.exec()

        if result == QMessageBox.StandardButton.Yes:
            to_remove = [item for item in self.clipboard_items if item.group == group_name]
            for item in to_remove:
                self.remove_item(item)
            self.groups.remove(group_name)
            self.config["groups"] = self.groups
            self.save_config()
            self.update_group_buttons()
            self.load_group_items("临时分组")
            logging.info(f"删除分组: {group_name}")

    def hide_window(self):
        self.hide()

    def clear_current_group(self) -> None:
        current_group = self.get_current_group()

        # 创建确认对话框，明确设置父窗口
        msg_box = QMessageBox(self)
        msg_box.setWindowTitle("确认")

        if current_group == "临时分组":
            msg_box.setText("确定要清空默认分组的所有内容吗？")
        else:
            msg_box.setText(f"确定要清空分组 '{current_group}' 的所有内容吗？")

        msg_box.setIcon(QMessageBox.Icon.Question)
        msg_box.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        msg_box.setDefaultButton(QMessageBox.StandardButton.No)  # 默认选择"否"

        # 应用主题样式
        if self.is_dark_mode:
            msg_box.setStyleSheet("""
                QMessageBox {
                    background-color: rgba(30, 30, 30, 0.95);
                    color: #e0e0e0;
                    border-radius: 12px;
                }
                QMessageBox QLabel {
                    color: #e0e0e0;
                }
                QMessageBox QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #e0e0e0;
                }
                QMessageBox QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                }
            """)

        # 执行对话框并获取结果
        result = msg_box.exec()

        if result == QMessageBox.StandardButton.Yes:
            to_remove = [item for item in self.clipboard_items if item.group == current_group]
            for item in to_remove:
                self.remove_item(item)

            self.load_group_items(current_group)
            logging.info(f"清空分组: {current_group}")

    def delete_item(self, item: QListWidgetItem) -> None:
        try:
            item_id = item.data(Qt.ItemDataRole.UserRole)
            item_data = next((data for data in self.clipboard_items if data.id == item_id), None)

            if item_data:
                self.remove_item(item_data)
                self.load_group_items(self.get_current_group())
                logging.info(f"删除项目: {item_data.id}")
            else:
                self.show_themed_message("警告", "未找到对应的项目数据", QMessageBox.Icon.Warning)

        except Exception as e:
            logging.error(f"删除项目时出错: {e}", exc_info=True)
            self.show_themed_message("错误", f"删除项目时出错: {str(e)}", QMessageBox.Icon.Critical)

    def remove_item(self, item: ClipboardItem) -> None:
        try:
            if item.content_type == "image" and isinstance(item.content, str):
                image_path = Path(item.content)
                if image_path.exists():
                    image_path.unlink()
                    logging.info(f"删除图片文件: {image_path}")

            self.clipboard_items.remove(item)
            self.save_data()

        except Exception as e:
            logging.error(f"移除项目时出错: {e}", exc_info=True)

    def open_settings(self) -> None:
        settings_dialog = QDialog(self)  # 设置父窗口为当前主窗口
        settings_dialog.setWindowTitle("设置")
        settings_dialog.setWindowModality(Qt.WindowModality.ApplicationModal)
        settings_dialog.resize(400, 250)  # 增加高度以适应主题设置选项

        # 根据当前主题设置对话框样式
        if self.is_dark_mode:
            settings_dialog.setStyleSheet("""
                QDialog {
                    background-color: rgba(30, 30, 30, 0.95);
                    border-radius: 12px;
                }
                QLabel {
                    color: #e0e0e0;
                }
                QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #e0e0e0;
                }
                QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                }
                QLineEdit, QSpinBox {
                    background-color: rgba(45, 45, 45, 0.9);
                    color: #e0e0e0;
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px;
                }
            """)
        else:
            settings_dialog.setStyleSheet("""
                QDialog {
                    background-color: rgba(255, 255, 255, 0.95);
                    border-radius: 12px;
                }
                QLabel {
                    color: #495057;
                }
                QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(250, 250, 250, 0.9), stop:1 rgba(240, 240, 240, 0.9));
                    border: 1px solid rgba(220, 220, 220, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #333333;
                }
                QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(245, 245, 245, 0.9), stop:1 rgba(235, 235, 235, 0.9));
                }
                QLineEdit, QSpinBox {
                    background-color: rgba(255, 255, 255, 0.9);
                    color: #1a1a1a;
                    border: 1px solid rgba(222, 226, 230, 0.8);
                    border-radius: 8px;
                    padding: 6px;
                }
            """)

        layout = QVBoxLayout()

        path_layout = QHBoxLayout()
        path_label = QLabel("数据文件保存路径:")
        path_value = QLabel(str(self.config_dir))
        path_btn = QPushButton("更改")
        path_btn.clicked.connect(self.change_data_path)

        path_layout.addWidget(path_label)
        path_layout.addWidget(path_value)
        path_layout.addWidget(path_btn)

        hotkey_layout = QHBoxLayout()
        hotkey_label = QLabel("全局热键:")
        hotkey_value = QLabel(self.hotkey)
        hotkey_btn = QPushButton("更改")
        hotkey_btn.clicked.connect(self.change_hotkey)

        hotkey_layout.addWidget(hotkey_label)
        hotkey_layout.addWidget(hotkey_value)
        hotkey_layout.addWidget(hotkey_btn)

        items_layout = QHBoxLayout()
        items_label = QLabel("每个分组最大项目数:")
        items_value = QLabel(str(self.max_items_per_group))
        items_btn = QPushButton("更改")
        items_btn.clicked.connect(self.change_max_items)

        items_layout.addWidget(items_label)
        items_layout.addWidget(items_value)
        items_layout.addWidget(items_btn)

        # 添加主题设置选项
        theme_layout = QHBoxLayout()
        theme_label = QLabel("主题模式:")
        theme_value = QLabel("深色模式" if self.is_dark_mode else "浅色模式")
        theme_btn = QPushButton("切换")
        theme_btn.clicked.connect(lambda: self.toggle_theme_dialog(settings_dialog, theme_value))

        theme_layout.addWidget(theme_label)
        theme_layout.addWidget(theme_value)
        theme_layout.addWidget(theme_btn)

        button_layout = QHBoxLayout()
        ok_btn = QPushButton("确定")
        ok_btn.clicked.connect(settings_dialog.accept)
        button_layout.addStretch()
        button_layout.addWidget(ok_btn)

        layout.addLayout(path_layout)
        layout.addLayout(hotkey_layout)
        layout.addLayout(items_layout)
        layout.addLayout(theme_layout)
        layout.addLayout(button_layout)

        settings_dialog.setLayout(layout)
        settings_dialog.show()
        settings_dialog.exec()

    def toggle_theme_dialog(self, dialog, label):
        """在设置对话框中切换主题"""
        self.toggle_theme()
        label.setText("深色模式" if self.is_dark_mode else "浅色模式")

        # 更新对话框样式
        if self.is_dark_mode:
            dialog.setStyleSheet("""
                QDialog {
                    background-color: rgba(30, 30, 30, 0.95);
                    border-radius: 12px;
                }
                QLabel {
                    color: #e0e0e0;
                }
                QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 0.9), stop:1 rgba(60, 60, 60, 0.9));
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #e0e0e0;
                }
                QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(60, 60, 60, 0.9), stop:1 rgba(70, 70, 70, 0.9));
                }
                QLineEdit, QSpinBox {
                    background-color: rgba(45, 45, 45, 0.9);
                    color: #e0e0e0;
                    border: 1px solid rgba(75, 75, 75, 0.8);
                    border-radius: 8px;
                    padding: 6px;
                }
            """)
        else:
            dialog.setStyleSheet("""
                QDialog {
                    background-color: rgba(255, 255, 255, 0.95);
                    border-radius: 12px;
                }
                QLabel {
                    color: #495057;
                }
                QPushButton {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(250, 250, 250, 0.9), stop:1 rgba(240, 240, 240, 0.9));
                    border: 1px solid rgba(220, 220, 220, 0.8);
                    border-radius: 8px;
                    padding: 6px 14px;
                    color: #333333;
                }
                QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(245, 245, 245, 0.9), stop:1 rgba(235, 235, 235, 0.9));
                }
                QLineEdit, QSpinBox {
                    background-color: rgba(255, 255, 255, 0.9);
                    color: #1a1a1a;
                    border: 1px solid rgba(222, 226, 230, 0.8);
                    border-radius: 8px;
                    padding: 6px;
                }
            """)

    def change_data_path(self) -> None:
        new_path = QFileDialog.getExistingDirectory(self, "选择数据保存路径", str(self.config_dir))
        if new_path and new_path != str(self.config_dir):
            try:
                # 复制现有数据到新路径
                new_config_dir = Path(new_path) / ".clipboard_helper"
                new_config_dir.mkdir(exist_ok=True)

                # 复制配置文件
                if self.config_path.exists():
                    shutil.copy2(str(self.config_path), str(new_config_dir / "config.json"))

                # 复制数据文件
                if self.data_path.exists():
                    shutil.copy2(str(self.data_path), str(new_config_dir / "data.json"))

                # 复制图片目录
                if self.images_dir.exists() and new_config_dir.joinpath("images").exists():
                    shutil.rmtree(str(new_config_dir.joinpath("images")))
                shutil.copytree(str(self.images_dir), str(new_config_dir / "images"))

                # 更新配置路径
                self.config_dir = new_config_dir
                self.config_path = self.config_dir / "config.json"
                self.data_path = self.config_dir / "data.json"
                self.images_dir = self.config_dir / "images"

                self.show_themed_message("成功", f"数据路径已更改为:\n{str(self.config_dir)}")
            except Exception as e:
                self.show_themed_message("错误", f"更改数据路径失败:\n{str(e)}", QMessageBox.Icon.Critical)

    def change_hotkey(self) -> None:
        current_hotkey = self.hotkey
        new_hotkey, ok = QInputDialog.getText(self, "更改热键", "请输入新的热键组合(例如: alt+z):", text=current_hotkey)
        if ok and new_hotkey and new_hotkey != current_hotkey:
            try:
                # 验证热键格式
                if "+" not in new_hotkey:
                    raise ValueError("热键格式不正确，必须包含'+'")

                self.hotkey = new_hotkey
                self.config["hotkey"] = new_hotkey
                self.save_config()

                # 重启热键监听
                self.setup_global_hotkey()

                self.show_themed_message("成功", f"全局热键已更改为: {new_hotkey}")
            except Exception as e:
                self.show_themed_message("错误", f"设置热键失败:\n{str(e)}", QMessageBox.Icon.Critical)

    def change_max_items(self) -> None:
        current_value = self.max_items_per_group
        new_value, ok = QInputDialog.getInt(
            self, "更改最大项目数", "请输入每个分组的最大项目数:",
            current_value, 10, 500, 10
        )
        if ok and new_value != current_value:
            self.max_items_per_group = new_value
            self.config["max_items_per_group"] = new_value
            self.save_config()
            self.show_themed_message("成功", f"每个分组最大项目数已更改为: {new_value}")

    def load_config(self) -> Dict[str, Any]:
        """加载配置文件"""
        try:
            if self.config_path.exists():
                with open(self.config_path, 'r', encoding='utf-8') as f:
                    return json.load(f)
        except Exception as e:
            logging.error(f"加载配置文件失败: {e}", exc_info=True)

        # 默认配置
        return {
            "groups": ["临时分组"],
            "max_items_per_group": 100,
            "hotkey": "alt+z",
            "dark_mode": False
        }

    def save_config(self) -> None:
        """保存配置文件"""
        try:
            with open(self.config_path, 'w', encoding='utf-8') as f:
                json.dump(self.config, f, ensure_ascii=False, indent=2)
        except Exception as e:
            logging.error(f"保存配置文件失败: {e}", exc_info=True)

    def load_data(self) -> List[ClipboardItem]:
        """加载剪贴板数据"""
        try:
            if self.data_path.exists():
                with open(self.data_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    return [ClipboardItem(**item_data) for item_data in data]
        except Exception as e:
            logging.error(f"加载数据文件失败: {e}", exc_info=True)

        return []

    def save_data(self) -> None:
        """保存剪贴板数据"""
        try:
            with open(self.data_path, 'w', encoding='utf-8') as f:
                json.dump([item.to_dict() for item in self.clipboard_items], f, ensure_ascii=False, indent=2)
        except Exception as e:
            logging.error(f"保存数据文件失败: {e}", exc_info=True)

    def closeEvent(self, event) -> None:
        """窗口关闭事件"""
        # 停止热键检查定时器
        if hasattr(self, 'hotkey_check_timer'):
            self.hotkey_check_timer.stop()

        self.hotkey_thread.stop()
        self.clipboard_thread.stop()
        logging.info("剪贴板助手已关闭")
        event.accept()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ClipboardHelper()
    window.show()
    sys.exit(app.exec())
